package site.psvm;

import site.psvm.model.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author leo
 * 泛型-边界通配符
 */
public class Demo2 {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        //上边界通配符 extends
        //可以将List<Integer>传入,因为它能接收 <? extends Number>
        extendsTest(list1);

        //下边界通配符 super
        List<Speaking> speakingList = new ArrayList<>();
        speakingList.add(new Bird());
        List<Swimming> swimmingList = new ArrayList<>();
        swimmingList.add(new Fish());
        //可以将它们传入,因为参数的泛型类型的实际类型参数都实现了传入对象的实际类型参数接口
        superTest(speakingList);
        superTest(swimmingList);
    }

    //上边界通配符 extends
    public static void extendsTest(List<? extends Number> list){
        //可以确定最大类型为Number,可以通过最大类型去获取数据
        //无法add,因为并不知道传入的实际类型,若父类无子类独有方法,取出时会出现类型转换异常,等于父类强转子类
        //list.add(new Integer(2));

        //取出时为转换为向上转型,安全
        Number number = list.get(0);
    }

    //下边界通配符 super
    public static void superTest(List<? super Person> list){
        //取出时为Object类型,因为传入对象的实际参数类型可能只实现了Person实现的某一个接口,直接向上转型
        Object object = list.get(0);

        //可以确定最小类型,所以可以以最小类型去写入数据（向上转型）。。
        //add时可以是Person或子类,一定实现了Person所实现的接口的全部方法
        list.add(new Person());
    }

    //无界通配符 ?
    public static void unboundTest(List<?> list){
        //类似于 <? extends Object>
        //可以确定最大类型为Object,可以通过Object获取,但无法写入
        //list.add("12");

        Object o = list.get(0);
    }
}
